from .FBOAttachment import FBOAttachment
from .GLInfo import GLInfo
from .utils import checktype
from .helper import get_dtype

from OpenGL import GL


class RBO(FBOAttachment):

    _basic_info = {
        "gen_func": GL.glGenRenderbuffers,
        "bind_func": GL.glBindRenderbuffer,
        "del_func": GL.glDeleteRenderbuffers,
        "target_type": GL.GL_RENDERBUFFER,
        "binding_type": GL.GL_RENDERBUFFER_BINDING,
        "need_number": True,
    }

    @checktype
    def __init__(
        self,
        width: int = 0,
        height: int = 0,
        samples: int = None,
        internal_format: GLInfo.internal_formats = GL.GL_DEPTH24_STENCIL8,
    ):
        FBOAttachment.__init__(self)

        self._samples = samples
        self._width = width
        self._height = height
        self._internal_format = internal_format
        self._param_changed = True

    def bind(self, update_fbo: bool = False, force_update_image: bool = False):
        FBOAttachment.bind(self, update_fbo, force_update_image)

        if self._param_changed or force_update_image:
            if self._samples is not None:
                GL.glRenderbufferStorageMultisample(
                    GL.GL_RENDERBUFFER,
                    self._samples,
                    self._internal_format,
                    self._width,
                    self._height,
                )
            else:
                GL.glRenderbufferStorage(
                    GL.GL_RENDERBUFFER, self._internal_format, self._width, self._height
                )
            self._param_changed = False

    @property
    def samples(self):
        return self._samples

    @samples.setter
    def samples(self, samples: int):
        if self._samples != samples:
            self._samples = samples
            self._param_changed = True

    @property
    def dtype(self):
        return get_dtype(self._internal_format)

    @checktype
    def malloc(
        self,
        width: int,
        height: int,
        samples: int = None,
        layers: int = None,
        internal_format: GLInfo.internal_formats = None,
    ):
        self.width = width
        self.height = height

        if internal_format is None:
            internal_format = internal_format

        if internal_format is None:
            internal_format = GL.GL_DEPTH24_STENCIL8

        self.internal_format = internal_format

        if samples is not None:
            self.samples = samples

    @property
    def width(self):
        return self._width

    @width.setter
    def width(self, width):
        if self._width != width:
            self._width = width
            self._param_changed = True

    @property
    def height(self):
        return self._height

    @height.setter
    def height(self, height):
        if self._height != height:
            self._height = height
            self._param_changed = True

    @property
    def internal_format(self):
        return self._internal_format

    @internal_format.setter
    @checktype
    def internal_format(self, format: GLInfo.internal_formats):
        if self._internal_format != format:
            self._internal_format = format
            self._param_changed = True
